/*
 * c_tabla.h
 *
 *  Created on: 27 Apr 2010
 *      Author: osky
 */

#include "c_tabla.h"


unsigned int c_tabla::get_pos (unsigned int pos)
             {
             unsigned int resultado;
             
              int nro_buffer = ( pos * sizeof(int) ) / LARGO_BLOQUE ;
              int pos_en_buffer = ( pos * sizeof(int) ) % LARGO_BLOQUE ;

              if(nro_buffer!=nro_buffer_en_memoria) 
            		{
            		 nro_buffer_en_memoria=nro_buffer;
            		}
                      
                buffer_tabla[nro_buffer].set_pos(pos_en_buffer);
                buffer_tabla[nro_buffer].get(&resultado);
                

              #ifdef _DEBUG_  	 
                printf("c_tabla get_pos pos:%d de la tabla. Corresponde a bloque:%d sub_pos: %d -> valor: %d\n", pos, nro_buffer, pos_en_buffer, resultado);
              #endif			


             return resultado; /*  buffer_tabla[pos];                               */
             }


int c_tabla::set_pos (unsigned int pos, unsigned int valor)
             {
               int nro_buffer = ( pos * sizeof(int) ) / LARGO_BLOQUE ;
               int pos_en_buffer = ( pos * sizeof(int) ) % LARGO_BLOQUE ;
               
        	#ifdef _DEBUG_  
                printf("Seteando pos:%d de la tabla. Corresponde a bloque:%d sub_pos: %d con valor=%d\n", pos, nro_buffer, pos_en_buffer,valor);
        	#endif	

              if(nro_buffer!=nro_buffer_en_memoria) 
            		{
            		 nro_buffer_en_memoria=nro_buffer;
            		}

        	  
                buffer_tabla[nro_buffer].set_pos(pos_en_buffer);
                buffer_tabla[nro_buffer].add(valor);

             return RES_OK;
             }


int c_tabla::copiar_pos (unsigned int pos_origen, unsigned int pos_destino)
             {
                /* buffer_tabla[pos_destino]=buffer_tabla[pos_origen];       */
             return RES_OK;
             }


int c_tabla::set_pos (unsigned int desde, unsigned int hasta, unsigned int valor)
	     {
	     unsigned int i;

	     for (i=desde; i<=hasta; i++)
	        {
	    	    set_pos(i,valor);
	        }
	     return RES_OK;


	     }

unsigned int c_tabla::total_reg ()
             {

             return BLOQUES_TABLA * LARGO_BLOQUE / sizeof(int);

             }



c_tabla::c_tabla()
        {

        bits_validos=EXTENSION_INICIAL;

        for (int i=0;i<BLOQUES_TABLA;i++)
        	{
        	  buffer_tabla[i].set_nro(i);
        	  
        	}


        }







int c_tabla::save()

	{
        for (int i=0;i<BLOQUES_TABLA;i++)
        	{
        	  #ifdef _DEBUG_
        	  printf("Grabando tabla, bloque: %d\n",i);
        	  #endif 

        	  buffer_tabla[i].save();        	  

        	}
        
        #ifdef _DEBUG_        	
        printf ("Bloques en la tabla: %d\n",BLOQUES_TABLA);	
        #endif 

        return RES_OK;

	}

int c_tabla::load()

	{
        for (int i=0;i<BLOQUES_TABLA;i++)
        	{
        	  buffer_tabla[i].load();

        	}
        
        nro_buffer_en_memoria=0;        	
        return RES_OK;

	}


unsigned int c_tabla::largo_tabla()
        {
         return (1<<bits_validos) * sizeof( unsigned int ) ;
        }


int c_tabla::actualizar_por_split ( unsigned int clave, unsigned int bucket_nuevo, int bit_split)
        {

        unsigned int mascara_1 = 0XFFFF<< (16-MAX_BITS_HASH) ;
        unsigned int mascara_2 = 0XFFFF>> (bit_split+1) ;
        unsigned int mascara_3 = 0X8000>> (bit_split) ;

        unsigned int desde= (( (clave | mascara_3) & ~mascara_2) & mascara_1) >> (16-MAX_BITS_HASH) ;
        unsigned int hasta= (( (clave | mascara_3) | mascara_2 ) & mascara_1) >> (16-MAX_BITS_HASH) ;

        	  #ifdef _DEBUG_
        printf (" Actualizando tabla, por split el bit %d en clave %X desde: %d hasta: %d \n", bit_split, clave , desde, hasta);
        printf (" mascara_1: %X  mascara_2: %X \n", mascara_1,mascara_2);
        	  #endif

        set_pos(desde,hasta,bucket_nuevo);

	if (bit_split>bits_validos) bits_validos=bit_split;

        return 0;

        }

unsigned int c_tabla::elementos_tabla()
	{
	
	return 1<<MAX_BITS_HASH;
	
	}


unsigned int c_tabla::obtener_nro_bucket(unsigned int clave)
        {

	unsigned int nro_bucket;
        /* Con los bits validos, calcula el tamaño de la tabla */

        /* Con los bits validos, calcula la posicion en la tabla */
	unsigned int pos = clave >> (16-MAX_BITS_HASH) ;

        /* Toma del disco la parte de la tabla correspondiente 		 */
        /* Lee de la tabla el Nro de bucket 				 */

        /* Devuelve el Nro de bucket					 */

        nro_bucket=get_pos(pos);

        return nro_bucket;

	}


int c_tabla::incrementar_bits_validos ()
        {
         int resultado;
         int l= largo_tabla();

          if (bits_validos<MAX_BITS_HASH)
            {

            for (int i=0; i < l ; i++)
        	{
        	 copiar_pos ( i , i + l );
        	}

            bits_validos++;

    	    resultado=1;
    	    }
          else resultado=0;
          return resultado;
        }



int c_tabla::dump(FILE *handler)
        {
        
        unsigned int elementos=elementos_tabla();

        unsigned int anterior=0xFFFF;
        unsigned int actual=0;
        
        
        #ifdef _DEBUG_  
        
        unsigned int bloques=BLOQUES_TABLA;        
        printf("Tabla de %d bits en %d bloques con %d elementos\n",bits_validos, bloques, elementos);
        #endif	
        
	fprintf(handler,"Tabla...\n");
	
       for (unsigned int i=0;i<elementos ;i++)
        	{
        	            actual=get_pos(i);
        	                if (actual!=anterior) { fprintf(handler,"%d ",actual);
        	            			        anterior=actual;
        	                                      }

        	}
        	
        fprintf(handler,"\n");	

	return RES_OK;
        }





